package com.cindata

import com.cindata.dictionary.ExecStatusDict
import com.cindata.dictionary.OverdueStateDict
import com.cindata.dictionary.PrepaymentTypeDict
import com.cindata.dictionary.RepaymentStateDict
import com.cindata.dictionary.RepaymentTypeDict
import com.cindata.dictionary.MortgageStatusDict

class RepaymentImport
{

    String repaymentNo
    // 还款编号
    EstateImportBatch batch
    //  所属导入批次
    Mortgage mortgage
    //  所属房贷(贷款)
    String contractNo
    //  贷款合同号
    String serialNumber
    // 贷款编号
    Date repaymentDate
    //  还款年月
    RepaymentTypeDict repaymentType
    //  还款类型
    BigDecimal shouldRepaymentAmount
    //  应还款金额（元）
    BigDecimal shouldRepaymentCapital
    //  应还款本金（元）
    BigDecimal shouldRepaymentInterest
    //  应还款利息（元）
    Date practicalChargeBackDate
    //  实际扣款日期
    BigDecimal practicalRepaymentAmount
    //  实际还款金额（元）
    BigDecimal practicalRepaymentCapital
    //  实际还款本金（元）
    BigDecimal practicalRepaymentInterest
    //  实际还款利息（不含罚息）（元）
    BigDecimal practicalRepaymentFine
    //  实际还罚息（元）
    Date overdueDate
    //  逾期年月
    OverdueStateDict overdueState
    //  逾期状态
    Integer continuousOverdueNumber
    //  连续逾期期数
    BigDecimal fineAmount
    // 罚息金额（元）
    PrepaymentTypeDict prepaymentType
    //  提前还款类型
    Integer beforePrepaymentDuration
    //  提前还款缩期前期数（月）
    Integer afterPrepaymentDuration
    // 提前还款缩期后期数（月）
    Boolean isCompute = false
    // 是否已经计算

    ExecStatusDict execStatus
    // 还款状态

    Date createdDate = new Date()
    Date modifiedDate = new Date()
    User createBy
    User modifyBy

    static belongsTo = [batch: EstateImportBatch, mortgage: Mortgage]

    RepaymentImport()
    {
    }

    RepaymentImport(EstateImportBatch batch, String contractNo, Date createdDate, User createBy)
    {
        this.batch = batch
        this.contractNo = contractNo
        this.createdDate = createdDate
        this.createBy = createBy
    }

    static mapping = {
        autowire true
    }

    static constraints = {
        repaymentNo nullable: true, blank: true, comment: '还款编号'
        batch nullable: true, blank: true, comment: '所属导入批次'
        mortgage nullable: true, blank: true, comment: '所属房贷(贷款)'
        contractNo maxSize: 64, nullable: true, blank: true, comment: '贷款合同号'
        serialNumber maxSize: 64, nullable: true, blank: true, comment: '贷款编号'
        repaymentDate nullable: true, blank: true, comment: '还款年月'
        repaymentType nullable: true, blank: true, comment: '还款类型'
        shouldRepaymentAmount precision: 15, scale: 2, nullable: true, blank: true, comment: '应还款金额（元）'
        shouldRepaymentCapital precision: 15, scale: 2, nullable: true, blank: true, comment: '应还款本金（元）'
        shouldRepaymentInterest precision: 15, scale: 2, nullable: true, blank: true, comment: '应还款利息（元）'
        practicalChargeBackDate nullable: true, blank: true, comment: '实际扣款日期'
        practicalRepaymentAmount precision: 15, scale: 2, nullable: true, blank: true, comment: '实际还款金额（元）'
        practicalRepaymentCapital precision: 15, scale: 2, nullable: true, blank: true, comment: '实际还款本金（元）'
        practicalRepaymentInterest precision: 15, scale: 2, nullable: true, blank: true, comment: '实际还款利息（不含罚息）（元）'
        practicalRepaymentFine precision: 15, scale: 2, nullable: true, blank: true, comment: '实际还罚息（不含罚息）（元）'
        overdueDate nullable: true, blank: true, comment: '逾期年月'
        overdueState nullable: true, blank: true, comment: '逾期状态'
        continuousOverdueNumber maxSize: 4, nullable: true, blank: true, comment: '连续逾期期数'
        fineAmount precision: 15, scale: 2, nullable: true, blank: true, comment: '罚息金额（元）'
        prepaymentType nullable: true, blank: true, comment: '提前还款类型'
        beforePrepaymentDuration maxSize: 4, nullable: true, blank: true, comment: '提前还款缩期前期数（月）'
        afterPrepaymentDuration maxSize: 4, nullable: true, blank: true, comment: '提前还款缩期后期数（月）'
        createBy nullable: true, blank: true, comment: '创建者'
        modifyBy nullable: true, blank: true, comment: '修改者'
        isCompute nullable: true, blank: true, comment: '是否经过计算'
        execStatus nullable: true, blank: true, comment: '还款状态'
    }

    // 把还款数据同步到贷款表中去
    def synRepaymentDataToMortgage()
    {
        if (this.isCompute)
        {
            return
        }
        // 找到贷款数据
        def curMortgage = this.mortgage
        if (!curMortgage)
        {
            return
        }
        // 还款期数是否能对上
        /*
        def shoudRepaymentDate = estate.getShouldRepaymentDate();
        if(!DateUtilService.isSameYearMonth(shoudRepaymentDate,repaymentDate)){
            return
        }
        */
        // 无还款状态不计算
        if (!this.repaymentType)
        {
            return
        }
        switch (this.repaymentType.code)
        {
        case "Normal":
            computeDateNormal(curMortgage)
            break
        case "InAdvance":
            computeDateInAdvance(curMortgage)
            break
        case "TurnOver":
            computeDateTurnOver(curMortgage)
            break
        case "Overdue":
            computeDateOverdue(curMortgage)
            break
        }
        this.isCompute = true
        this.save()
    }

    // 数据请0
    def setZero(Mortgage mortgage)
    {
        if (!mortgage.loansBalance)
        {
            mortgage.loansBalance = 0
        }
        if (!mortgage.curRecycleTotalCapital)
        {
            mortgage.curRecycleTotalCapital = 0
        }
        if (!mortgage.curNormalTotalCapital)
        {
            mortgage.curNormalTotalCapital = 0
        }
        if (!mortgage.curInAdvanceTotalCapital)
        {
            mortgage.curInAdvanceTotalCapital = 0
        }
        if (!mortgage.curOverdueTotalCapital)
        {
            mortgage.curOverdueTotalCapital = 0
        }
        if (!mortgage.curRecycleTotalInterest)
        {
            mortgage.curRecycleTotalInterest = 0
        }
        if (!mortgage.remainTime)
        {
            mortgage.remainTime = 0
        }
        if (!mortgage.curHasPaymentTODuration)
        {
            mortgage.curHasPaymentTODuration = 0
        }
        if (!mortgage.curHasPaymentDuration)
        {
            mortgage.curHasPaymentDuration = 0
        }
    }

    // 正常还款计算数据
    def computeDateNormal(Mortgage mortgage)
    {
        setZero(mortgage)
        //  每笔贷款的贷款余额=原贷款余额-当期实际还款金额
        mortgage.loansBalance = mortgage.loansBalance - this.practicalRepaymentAmount
        //  每笔贷款的当前回收总本金=原回收总本金+当期实际还款本金
        mortgage.curRecycleTotalCapital = mortgage.curRecycleTotalCapital + this.practicalRepaymentCapital
        mortgage.curNormalTotalCapital = mortgage.curNormalTotalCapital + this.practicalRepaymentCapital

        // 每笔贷款的当前回收总利息（不含罚息）=原回收总利息+当期实际还款利息
        mortgage.curRecycleTotalInterest = mortgage.curRecycleTotalInterest + this.practicalRepaymentInterest
        // 当前剩余还款期数=原剩余还款期数-1
        mortgage.remainTime = mortgage.remainTime - 1
        // 原当前已还款期数(含转逾期)=原当前已还款期数(含转逾期)+1
        mortgage.curHasPaymentTODuration = mortgage.curHasPaymentTODuration + 1
        // 当前已还款期数(不含转逾期)=当前已还款期数+1
        mortgage.curHasPaymentDuration = mortgage.curHasPaymentDuration + 1

        // 状态改为正常
        mortgage.curRepaymentState = RepaymentStateDict.findByName('Normal')
        // 逾期期数
        mortgage.curOverdueDuration = 0
        // 最后还款日期
        mortgage.lastPayAt = this.practicalChargeBackDate

        // 是否还清计算
        computeIsPayOff(mortgage)
        mortgage.save()
    }

    // 提前还款计算数据
    def computeDateInAdvance(Mortgage mortgage)
    {
        setZero(mortgage)
        //  每笔贷款的贷款余额=原贷款余额-当期实际还款金额
        mortgage.loansBalance = mortgage.loansBalance - this.practicalRepaymentAmount
        //  每笔贷款的当前回收总本金=原回收总本金+当期实际还款本金
        mortgage.curRecycleTotalCapital = mortgage.curRecycleTotalCapital + this.practicalRepaymentCapital
        mortgage.curInAdvanceTotalCapital = mortgage.curInAdvanceTotalCapital + this.practicalRepaymentCapital

        // 每笔贷款的当前回收总利息（不含罚息）=原回收总利息+当期实际还款利息
        mortgage.curRecycleTotalInterest = mortgage.curRecycleTotalInterest + this.practicalRepaymentInterest
        // 当前剩余还款期数（提前还款时）=缩期后期数
        mortgage.remainTime = this.afterPrepaymentDuration
        // 原当前已还款期数(含转逾期)=原当前已还款期数(含转逾期)+（提前还款缩期前期数-提前还款缩期后期数）
        mortgage.curHasPaymentTODuration = mortgage.curHasPaymentTODuration + (this.beforePrepaymentDuration - this.afterPrepaymentDuration)
        // 当前已还款期数(不含转逾期)= 当前已还款期数(不含转逾期)+（提前还款缩期前期数-提前还款缩期后期数）
        mortgage.curHasPaymentDuration = mortgage.curHasPaymentDuration + (this.beforePrepaymentDuration - this.afterPrepaymentDuration)

        // 状态改为正常
        mortgage.curRepaymentState = RepaymentStateDict.findByName('Normal')
        // 逾期期数
        mortgage.curOverdueDuration = 0
        // 最后还款日期
        mortgage.lastPayAt = this.practicalChargeBackDate

        // 是否还清计算
        computeIsPayOff(mortgage)
        mortgage.save()
    }

    // 转逾期计算数据
    def computeDateTurnOver(Mortgage mortgage)
    {
        setZero(mortgage)
        //  每笔贷款的贷款余额=原贷款余额+罚息
        // mortgage.loansBalance = mortgage.loansBalance + this.fineAmount // TODO
        mortgage.loansBalance = mortgage.loansBalance
        // 当前剩余还款期数=原剩余还款期数+1
        mortgage.remainTime = mortgage.remainTime + 1

        if (this.overdueState.code == 'NoPay')
        {
            // 未还
            // 状态改为已逾期
            mortgage.curRepaymentState = RepaymentStateDict.findByName('Overdue')
            // 逾期期数
            mortgage.curOverdueDuration = continuousOverdueNumber
        }
        else
        {
            // 已还
            // 状态改为正常
            mortgage.curRepaymentState = RepaymentStateDict.findByName('Normal')
            // 逾期期数
            mortgage.curOverdueDuration = 0
            // 最后还款日期
            mortgage.lastPayAt = this.practicalChargeBackDate
        }
        mortgage.save()
    }

    // 逾期还款计算数据
    def computeDateOverdue(Mortgage mortgage)
    {
        setZero(mortgage)
        //  每笔贷款的贷款余额=原贷款余额-当期实际还款金额
        mortgage.loansBalance = mortgage.loansBalance - this.practicalRepaymentAmount
        //  每笔贷款的当前回收总本金=原回收总本金+当期实际还款本金
        mortgage.curRecycleTotalCapital = mortgage.curRecycleTotalCapital + this.practicalRepaymentCapital
        mortgage.curOverdueTotalCapital = mortgage.curOverdueTotalCapital + this.practicalRepaymentCapital

        // 每笔贷款的当前回收总利息（不含罚息）=原回收总利息+当期实际还款利息
        mortgage.curRecycleTotalInterest = mortgage.curRecycleTotalInterest + this.practicalRepaymentInterest
        // 每笔贷款的当前回收总罚息=原回收总罚息+当期实际还罚息
        mortgage.curRecycleTotalFine = mortgage.curRecycleTotalFine + this.practicalRepaymentFine
        // 当前剩余还款期数=原剩余还款期数-1
        mortgage.remainTime = mortgage.remainTime - 1
        // 原当前已还款期数(含转逾期)=原当前已还款期数(含转逾期)+1
        mortgage.curHasPaymentTODuration = mortgage.curHasPaymentTODuration + 1
        // 最后还款日期
        mortgage.lastPayAt = this.practicalChargeBackDate

        // 是否还清计算
        computeIsPayOff(mortgage)
        mortgage.save()
    }

    // 计算贷款当前还款状态
    def computeIsPayOff(Mortgage mortgage)
    {
        if (mortgage.remainTime == 0 && mortgage.loansBalance == 0)
        {
            mortgage.curRepaymentState = RepaymentStateDict.findByName('Payoff')
            mortgage.payOffAt = this.repaymentDate
            mortgage.mortgageStatus = MortgageStatusDict.findByCode('2')
        }
        else
        {
            if (this.repaymentType.code == 'TurnOver')
            {
                mortgage.mortgageStatus = MortgageStatusDict.findByCode('3')
            }
            else
            {
                mortgage.mortgageStatus = MortgageStatusDict.findByCode('1')
            }
        }
    }

    def springSecurityService
    def beforeInsert()
    {
        //如果该还款记录不存在，则去同步贷款数据
        def repaymentImport = RepaymentImport.findByRepaymentNoAndSerialNumber(this.repaymentNo, this.serialNumber)
        if(!repaymentImport)
        {
            println this.repaymentNo+"还款成功"
            this.isCompute = false
        }
        else
        {
            println this.repaymentNo+"还款记录已存在，还款失败"
            this.isCompute = true
        }
        def username = springSecurityService?.getPrincipal()?.username
        def user = User.findByUsername(username)
        def matchMortgage = Mortgage.findBySerialNumberAndAccount(this.serialNumber, user?.account)
        if (!matchMortgage)
        {
            println this.repaymentNo+"未匹配到贷款,还款失败"
            this.isCompute = true
            return
        }
        this.mortgage = matchMortgage
    }

    def afterInsert()
    {
        if(!this.isCompute)
        {
            this.synRepaymentDataToMortgage()
            this.execStatus =  ExecStatusDict.SUCCESS()
        }
        else
        {
            this.execStatus =  ExecStatusDict.FAILURE()
        }
    }
}
